package com.egzosn.figure.qiniu.api;

import com.egzosn.figure.common.api.FigureBedConfigStorage;
import com.egzosn.figure.common.api.FigureBedService;
import com.egzosn.figure.common.bean.BaseResourceInfo;
import com.egzosn.figure.common.bean.ProcessingResults;
import com.egzosn.figure.common.bean.ResourceInfo;
import com.egzosn.figure.qiniu.bean.ZoneType;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Client;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.util.Auth;
import com.qiniu.util.StringMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;


/**
 *  七牛云服务
 * @author egan
 *         email egzosn@gmail.com
 *         date 2018/8/20.20:19
 */
public class QiNiuFigureBedService implements FigureBedService {

    private final  static Logger logger =  LoggerFactory.getLogger(QiNiuFigureBedService.class);;
    /**
     * 配置信息
     */
    private FigureBedConfigStorage configStorage;
    /**
     * 授权对象
     */
    private Auth auth;
    /**
     *  空间资源管理
     */
    private BucketManager bucketManager;
    /**
     * 上传管理器
     */
    private UploadManager uploadManager;
    /**
     * 定义七牛云上传的相关策略
     */
    private StringMap putPolicy;
    private Client client;
    //    private String

    public QiNiuFigureBedService(FigureBedConfigStorage configStorage) {
        setConfigStorage(configStorage);
    }

    public QiNiuFigureBedService() {

    }

    public FigureBedConfigStorage getConfigStorage() {
        return configStorage;
    }

    public void putPolicy(StringMap putPolicy){
        this.putPolicy = putPolicy;
        if (null != this.putPolicy ){
            return;
        }

        this.putPolicy = new StringMap();
//        this.putPolicy.put("returnBody", "{\"key\":\"$(key)\",\"hash\":\"$(etag)\",\"bucket\":\"$(bucket)\",\"width\":$(imageInfo.width), \"height\":${imageInfo.height}}");
       //自定义上传的文件名字
//       this.putPolicy.put("saveKey", UUID.randomUUID().toString());
    }

    public void setConfigStorage(FigureBedConfigStorage configStorage) {
        this.configStorage = configStorage;

        putPolicy(((QiNiuFigureBedConfigStorage)configStorage).getPutPolicy());


        auth =  Auth.create(configStorage.getUserName(), configStorage.getSecretKey());
        Configuration cfg = new Configuration(ZoneType.valueOf(configStorage.getHostname()).getZone());
        client = new Client(cfg);
        bucketManager = new BucketManager(auth, client);
        uploadManager = new UploadManager(client, null);

    }



    /**
     * 授权
     */
    public ProcessingResults auth() {
        ProcessingResults results = new ProcessingResults();
        results.setData(this.auth.uploadToken(configStorage.getDataBase(), null, configStorage.getClientTimeout(), putPolicy));
       return results;
    }

    /**
     * 存储
     *
     * @param body 资源信息
     * @return 处理结果
     */
    public ProcessingResults store(ResourceInfo body) {
        try {
            Response response = uploadManager.put(body.getFile(), body.getFileName(), auth().getData().toString(), putPolicy, body.getContentType());
            ProcessingResults results = new ProcessingResults();
            results.setData(response.bodyString());
            return results;
        } catch (QiniuException e) {
            logger.error(body.pathname() + "上传文件失败！", e);
        }

        return ProcessingResults.ERROR(body.pathname() + "上传文件失败！");
    }

    /**
     * 列出服务器上文件和目录
     *
     * @param delimiter --指定目录分隔符，列出所有公共前缀（模拟列出目录效果）。缺省值为空字符串
     * @param prefix 文件名表达式
     * @return 匹配成功的文件列表， 未匹配成功则返回空
       *
     */
    public BucketManager.FileListIterator listRemoteFiles(String delimiter, String prefix) {
        //每次迭代的长度限制，最大1000，推荐值 1000
        int limit = 1000;
        BucketManager.FileListIterator fileListIterator = bucketManager.createFileListIterator(configStorage.getDataBase(), prefix, limit, delimiter);
        return fileListIterator;

    }

    public boolean exists(BaseResourceInfo body) {
        BucketManager.FileListIterator fileListIterator = listRemoteFiles(configStorage.getDataBase(), body.pathname());
        return fileListIterator.hasNext() && fileListIterator.next().length > 0;
    }






    /**
     * 获取资源文件
     *
     * @param body
     * @return 资源文件
     */
    public ProcessingResults retrieveResource(BaseResourceInfo body) {

        String domainOfBucket = configStorage.getAccessAddress();
        String encodedFileName = null;
        try {
            encodedFileName = URLEncoder.encode(body.pathname(), "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        String publicUrl = String.format("%s/%s", domainOfBucket, encodedFileName);
        long expireInSeconds = 3600;//1小时，可以自定义链接过期时间
        String downloadUrl = auth.privateDownloadUrl(publicUrl, expireInSeconds);

        try {
            Response response = client.get(downloadUrl);
            ProcessingResults results = new ProcessingResults();
            results.setData( response.bodyStream());
            return results;
        } catch (QiniuException e) {
            logger.error(body.pathname() + "文件获取失败！", e);
        }
        return ProcessingResults.ERROR(body.pathname() + "文件获取失败！");
    }

    /**
     * 删除
     *
     * @param body 资源信息
     * @return 处理结果
     */
    public ProcessingResults delete(BaseResourceInfo body) {
        String domainOfBucket = configStorage.getAccessAddress();
        try {
            Response response = bucketManager.delete(domainOfBucket, body.pathname());
            return ProcessingResults.SUCCESS;
        } catch (QiniuException e) {
            logger.error(body.pathname() + "文件删除失败！", e);
        }

        return ProcessingResults.ERROR(body.pathname() + "文件删除失败！");

    }


}
